Local Actor API
The “Local Actor API” is a HTTP JSON-REST based interface for requesting AMQP 1.0 endpoints/connections for data subscription and data delivery. If the creation of the “delivery” or “subscription” is successful, the delivery/subscription can be “polled” in order to obtain the connection details of the related AMQP connections
A Swagger of the API itself, can be found here: Local Actor API v2
AMQP connection management
Even after successful connection of the initial AMQP connection(s), the “delivery”/”subscription” needs to be monitored by the local actor since it could be possible that the AMQP server replaces one or more “endpoints”, requiring the local actor to setup new AMQP connections in order to be able to continue producing or consuming data.
Authentication
The API authentication is based on TLS Client Authentication. The API is exposed over HTTPS using TLS v1.3. A client-side certificate is required to access the API. The client certificate’s “common name” is used for identification of the client. The AMQP connections are also secured by TLS v1.3 and require a client-side certificate for authentication. The same client certificate must be used for both the API and the AMQP connections
Curl example
Quick check if you can connect to the API.
Download the certificate chain for the server.
openssl s_client -showcerts -servername sp-actor-api.interchange.mobilidata.vlaanderen.be -connect sp-actor-api.interchange.mobilidata.vlaanderen.be:443 > cacert.pem
Do a curl to see your active subscriptions. This should be an empty list in the beginning.
curl --location https://sp-actor-api.interchange.mobilidata.vlaanderen.be/<clientCommonName>/subscriptions --cert <yourCertificate>.cert --key <yourPrivateRSAKey>.pem --cacert cacert.pem
In the result is a version shown. You can use this version in all the following commands.
API
Subscriptions
POST/{clientCommonName}/subscriptions
Create one or more subsriptions for data consumption.
Request
POST /subscriptions HTTP/1.1
Host: <hostname>
Content-Type: application/json
{
"name": "<clientCommonName>",
"subscriptions": [
{
"selector": "<JMS selector>"
}
],
"version": "<version>"
}
| Name | Description |
|---|---|
| ClientCommonName | The common name of the client certificate used for authentication |
| subscriptions | List of subscriptions to be created |
| subscription.selector | JMS selector used to filter the messages (if left empty with empty string, all available data will be made available) |
| version | Version of the API. For future backwards compatibility on JSON level |
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"name": "<clientCommonName>",
"subscriptions": [
{
"id": "<subscriptionId>",
"path": "<API base URL>/<clientcommonName>/subscriptions/<subscriptionId>",
"selector": "<JMS selector from request>",
"lastUpdatedTimestamp": <timestamp>
"status": "<subscription status enum>"
}
],
"version": "<version>"
}
| Name | Description |
|---|---|
| ClientCommonName | The common name of the client certificate used for authentication |
| subscriptions | List of subscriptions that should be created |
| subscription.id | The unique identifier of the subscription |
| subscription.path | The URL to the subscription |
| subscription.selector | JMS selector used to filter the messages (if left empty with empty string, all available data will be made available) |
| subscription.lastUpdatedTimestamp | Timestamp of the last update of the subscription |
| subscription.status | The status of the subscription |
| version | Version of the API. For future backwards compatibility on JSON level |
The subscription status can be one of the following values:
- REQUESTED: the subscription is requested but not yet created
- CREATED: the subscription is created and ready to be used
- ILLEGAL: the subscription is refused
- NOT_VALID: the subscription is refused becasuse teh 'JMS selector' is not valid
- NO_OVERLAP: the subscription is refused because there is no available capability (dataset) matching the 'JMS selector'
- RESUBSCRIBE: the subscription is accepted and created, connections can be made -however since the subscription has been created one or more capabilities have been added in scope of this subscription. Optionally recreate the subscription in order to also start receiving data from the new capabilities
GET/{clientCommonName}/subscriptions
Retrieve all subscriptions
Request
GET <API base URL>/<clientCommonName>/subscriptions/ HTTP/1.1
Host: <hostname>
Content-Type: application/json
Response
See POST /{clientCommonName}/subscriptions response. The only difference is that all created subscriptions are returned instead of the just created ones
GET/{clientCommonName}/subscriptions/{subscriptionId}
Retrieve the details of a single subscription. This should be used for polling the subscription in order to monitor its state and endpoints.
Request
GET <API base URL>/<clientCommonName>/subscriptions/<subscriptionId> HTTP/1.1
Host: <hostname>
Content-Type: application/json
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "<subscriptionId>",
"endpoints": [
{
"host": "<AMQP host>",
"port": "<AMQP port>",
“source”: “< AMQP source destination>”,
"maxBandwidth":<bytes/s>,
"maxMessageRate":<message /s>
}
],
"path": "//subscriptions/",
"selector": "<JMS selector>",
"lastUpdatedTimestamp": <timestamp>
"status": "<subscription status enum>"
}
| Name | Description |
|---|---|
| subscription.id | The unique identifier of the subscription |
| subscription.endpoints | List of AMQP endpoints |
| endpoint.host | The hostname of AMQP server to connect to |
| endpoint.port | The port of AMQP server to connect to |
| endpoint.source | The AMQP source destination address to read from |
| endpoint.maxBandwidth | The maximum bandwidth (in byttes per second) of the AMQP connection. The client should be able to handle the maximum bandwidth (can be / omitted when unknown) |
| endpoint.maxMessageRate | The maximum message rate (in messages per second) of the AMQP connection. The client should be able to handle the maximum message rate (can be / omitted when unknown) |
| subscription.path | The path on which the subscription state can be polled on |
| subscription.selector | JMS selector used to filter the messages |
| subscription.lastUpdatedTimestamp | Timestamp of the last update of the subscription |
| subscription.status | The status of the subscription |
The subscription status can be one of the following values:
- REQUESTED: the subscription is requested but not yet created
- CREATED: the subscription is created and ready to be used
- ILLEGAL: the subscription is refused
- NOT_VALID: the subscription is refused becasuse teh 'JMS selector' is not valid
- NO_OVERLAP: : the subscription is refused because there is no available capability (dataset) matching the “JMS selector” RESUBSCRIBE: the subscription is accepted and created, connections can be made - however since the subscription has been created one or more capabilities have been added in scope of this subscription. Optionally recreate the subscription in order to also start receiving data from these new capabilities
DELETE/{clientCommonName}/subscriptions/{subscriptionId}
Removes a subscription.
Request
DELETE <API base URL>/<clientCommonName>/subscriptions/<subscriptionId> HTTP/1.1
Host:<hostname>
Response
HTTP/1.1 204 OK
Deliveries
POST/{clientCommonName}/deliveries
Create one or more deliveries for sending data.
Request
POST <API base URL>/<clientCommonName>//deliveries HTTP/1.1
Host: <hostname>
Content-Type: application/json
{
"name": "<clientCommonName>",
"deliveries": [
{
"selector": "<JMS selector>"
}
],
"version": "<version>"
}
| Name | Description |
|---|---|
| ClientCommonName | The common name of the client certificate used for authentication |
| deliveries | List of deliveries to be created |
| delivery.selector | JMS selector used to filter the messages (if left empty with empty string, all available data will be made available) |
| version | Version of the API. For future backwards compatibility on JSON level |
The “common name” of the client
- This must match the common name element (RDN) of the X.509 certificate’s distinguished name (DN); also known as the CN element of the “subject”
- This field is also present in the path and must be identical to this field value
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"name": "<clientCommonName",
"deliveries": [
{
"id": "<deliveryId",
"path": "<API base URL>/<clientCommonName>/deliveries/<deliveryId",
"selector": "<JMS selector from request>",
"lastUpdatedTimestamp": <timestamp>,
"status": "<delivery status enum>"
}
],
"version": "<version>”
}
| Name | Description |
|---|---|
| ClientCommonName | The common name of the client certificate used for authentication |
| deliveries | List of created deliveries |
| delivery.id | The unique identifier of the delivery |
| delivery.path | The path on which the delivery state can be polled on |
| delivery.selector | JMS selector used to filter the messages (if left empty with empty string, all available data will be made available) |
| delivery.lastUpdatedTimestamp | Timestamp of the last update of the delivery |
| delivery.status | The status of the delivery |
| version | Version of the API. For future backwards compatibility on JSON level |
The delivery status can be one of the following values:
- REQUESTED: the delivery is requested but not yet created
- CREATED: the delivery is created and ready to be used
- ILLEGAL: the delivery is refused
- NOT_VALID: the delivery is refused becasuse teh 'JMS selector' is not valid
- NO_OVERLAP: the delivery is refused because there is no available capability (dataset) matching the 'JMS selector'
GET/{clientCommonName}/deliveries
Retrieve all deliveries.
Request
GET <API base URL>/<clientCommonName>/deliveries HTTP/1.1
Host: <hostname>
Content-Type: application/json
Response
See POST /{clientCommonName}/deliveries response. The only difference is that all created deliveries are returned instead of the just created ones.
GET/{clientCommonName}/deliveries/{deliveryId}
Retrieve the details of a single delivery. This should be used for polling the delivery in order to monitor its state and endpoints.
Request
GET <API base URL>/<clientCommonName>/deliveries/<deliveryId> HTTP/1.1
Host: <hostname>
Content-Type: application/json
Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "<deliveryId>",
"endpoints": [
{
"host": "<AMQP host>",
"port": "<AMQP port",
"selector": "<AMQP target destination>",
"maxBandwidth":<bytes/s>,
"maxMessageRate":<message/s>
}
],
"path": "<API base URL>/<clientCommonName>/deliveries/<deliveryId>",
"selector": "<JMS selector from delivery>",
"lastUpdatedTimestamp": <timestamp>,
"status": "<delivery status enum>"
}
| Name | Description |
|---|---|
| delivery.id | The unique identifier of the delivery |
| delivery.endpoints | List of AMQP endpoints |
| endpoint.host | The hostname of AMQP server to connect to |
| endpoint.port | The port of AMQP server to connect to |
| endpoint.source | The AMQP source destination address to read from |
| endpoint.maxBandwidth | The maximum bandwidth (in bytes per second) of the AMQP connection. The client should be able to handle the maximum bandwidth (can be / omitted when unknown) |
| endpoint.maxMessageRate | The maximum message rate (in messages per second) of the AMQP connection. The client should be able to handle the maximum message rate (can be / omitted when unknown) |
| delivery.path | The path on which the delivery state can be polled on |
| delivery.selector | JMS selector used to filter the messages |
| delivery.lastUpdatedTimestamp | Timestamp of the last update of the delivery |
| delivery.status | The status of the delivery |
The delivery status can be one of the following values:
- REQUESTED: the delivery is requested but not yet created
- CREATED: the delivery is created and ready to be used
- ILLEGAL: the delivery is refused
- NOT_VALID: the delivery is refused becasuse teh 'JMS selector' is not valid
- NO_OVERLAP: the delivery is refused because there is no available capability (dataset) matching the “JMS selector” RESUBSCRIBE: the delivery is accepted and created, connections can be made - however since the delivery has been created one or more capabilities have been added in scope of this delivery. Optionally recreate the delivery in order to also start sending data to these new capabilities
DELETE/{clientCommonName}/deliveries/{deliveryId}
Remove a delivery.
Request
DELETE <API base URL>/<clientCommonName>/deliveries/<deliveryId> HTTP/1.1
Host: <hostname>
Response
HTTP/1.1 204 OK